package com.guang.springbootexception.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class JsonUtil {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final Map<Class<?>, ObjectReader> readerMap = new ConcurrentHashMap();
    private static final Map<Class<?>, ObjectWriter> writerMap = new ConcurrentHashMap();
    private static final JsonFactory jsonFactory = new JsonFactory();
    private static final Map<Class<?>, JavaType> collectionElementMap = new ConcurrentHashMap();

    public JsonUtil() {
    }

    private static JavaType getJavaType(Class<?> targetClass) {
        Object javaType;
        if ((javaType = (JavaType)collectionElementMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((javaType = (JavaType)collectionElementMap.get(targetClass)) == null) {
                    javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, targetClass);
                    collectionElementMap.put(targetClass, (JavaType) javaType);
                }
            }
        }

        return (JavaType)javaType;
    }

    public static <T> List<T> parseJsonStringToListObject(String jsonString, Class<T> targetClass) throws Exception {
        ObjectReader reader = getObjectReader(List.class);
        JavaType javaType = getJavaType(targetClass);
        return (List)reader.readValue(jsonFactory.createParser(jsonString), javaType);
    }

    public static <T> List parseObjectListType(List<?> objectList, Class<T> targetClass) throws Exception {
        List<T> result = new ArrayList(objectList.size());
        Iterator var3 = objectList.iterator();

        while(var3.hasNext()) {
            Object object = var3.next();
            result.add(parseObjectToObject(object, targetClass));
        }

        return result;
    }

    public static <T> T parseObjectToObject(Object object, Class<T> targetClass) throws Exception {
        return parseJsonStringToObject(parseObjectToJsonString(object), targetClass);
    }

    public static <T> T parseJsonStringToObject(String jsonString, Class<T> targetClass) throws Exception {
        ObjectReader reader = getObjectReader(targetClass);
        return reader.readValue(jsonString);
    }

    public static String parseObjectToJsonString(Object object) throws Exception {
        ObjectWriter writer = getObjectWriter(object.getClass());
        return writer.writeValueAsString(object);
    }

    private static ObjectReader getObjectReader(Class<?> targetClass) {
        ObjectReader reader;
        if ((reader = (ObjectReader)readerMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((reader = (ObjectReader)readerMap.get(targetClass)) == null) {
                    reader = objectMapper.readerFor(targetClass);
                    readerMap.put(targetClass, reader);
                }
            }
        }

        return reader;
    }

    private static ObjectWriter getObjectWriter(Class<?> targetClass) {
        ObjectWriter writer;
        if ((writer = (ObjectWriter)writerMap.get(targetClass)) == null) {
            synchronized(targetClass) {
                if ((writer = (ObjectWriter)writerMap.get(targetClass)) == null) {
                    writer = objectMapper.writerFor(targetClass);
                    writerMap.put(targetClass, writer);
                }
            }
        }

        return writer;
    }

    static {
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
    }
}